/*******************************************************************************
 * Copyright (c) 2010, 2018 西安秦晔信息科技有限公司
 * Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *******************************************************************************/
package com.qinyeit.configuration;

import com.qinyeit.serviceapp.security.realm.ManagementAccountRealm;
import com.qinyeit.webapp.security.AccessTokenSessionManager;
import com.qinyeit.webapp.security.RedisSessionDao;
import com.qinyeit.webapp.security.ShiroSessionRedisTemplate;
import com.qinyeit.webapp.security.quartz.QuartzSessionValidationScheduler;
import com.qinyetech.springstage.core.security.RetryLimitHashedCredentialsMatcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnectionFactory;

import java.net.UnknownHostException;

/**
 * <p>ClassName: com.qinyeit.shirostarterdemo.configuration.ShiroConfiguration
 * <p>Function: shiro配置
 * <p>date: 2018-08-10 13:24
 *
 * @author wuqing
 * @version 1.0
 * @since JDK 1.8
 */
@Slf4j
@Configuration
@EnableAspectJAutoProxy
public class ShiroConfiguration extends ShiroWebAutoConfiguration {

    /**
     * 用来存储session
     * @param redisConnectionFactory
     * @return
     * @throws UnknownHostException
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE) //设置为高级别，优先加载
    public ShiroSessionRedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        ShiroSessionRedisTemplate template = new ShiroSessionRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @Override
    protected SessionManager sessionManager() {
        return accessTokenSessionManager();
    }

    @Bean
    public SessionDAO sessionDAO(ShiroSessionRedisTemplate shiroSessionRedisTemplate){
        RedisSessionDao sessionDao=new RedisSessionDao(shiroSessionRedisTemplate);
        return sessionDao;
    }

    private SessionManager accessTokenSessionManager() {
        AccessTokenSessionManager webSessionManager = new AccessTokenSessionManager();
        webSessionManager.setSessionIdCookie(super.sessionCookieTemplate());
        webSessionManager.setSessionFactory(sessionFactory());
        webSessionManager.setSessionDAO(sessionDAO());
        webSessionManager.setDeleteInvalidSessions(true);
        webSessionManager.setSessionValidationSchedulerEnabled(true);
        webSessionManager.setSessionValidationScheduler(new QuartzSessionValidationScheduler(webSessionManager));//删除无效的session
      //  webSessionManager.setGlobalSessionTimeout(); //全局session过期时间，单位毫秒 默认 30分钟
        return webSessionManager;
    }

    @Bean
    public Realm managementAccountRealm() {
        ManagementAccountRealm realm=new ManagementAccountRealm();
        realm.setCredentialsMatcher(retryLimitHashedCredentialsMatcher());
        return realm;
    }

    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        chainDefinition.addPathDefinition("/management/jcaptcha", "anon");
        chainDefinition.addPathDefinition("/logout", "logout");
        chainDefinition.addPathDefinition("/management/signin", "authc");
        chainDefinition.addPathDefinition("/management/organization/merchantGroups/**","anon");
        chainDefinition.addPathDefinition("/management/image/**","anon");
        chainDefinition.addPathDefinition("/management/dishes/dishess/saveStoreInfos","anon");
//        chainDefinition.addPathDefinition("/management/organization/printSettingOrders/create","anon");
//        chainDefinition.addPathDefinition("/management/organization/printSettingOrders/show","anon");
        chainDefinition.addPathDefinition("/**", "authc,signv"); // need to accept POSTs from the login form
//        chainDefinition.addPathDefinition("/**", "authc"); // fixme 生产环境需要验证签名 signv
        return chainDefinition;
    }

    @Bean("credentialsMatcher")
    @Order
    public RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher() {
        RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher(new MemoryConstrainedCacheManager());
        credentialsMatcher.setHashAlgorithmName("md5");
        credentialsMatcher.setHashIterations(2);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }
    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){

        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setUsePrefix(true);

        return defaultAdvisorAutoProxyCreator;
    }



}
